﻿/**	@file		lines.hpp
 *	@date		(2007-09-15 13:46:55)/(2007-09-15 13:46:55)
 *-----------------------------------------------------------------------------
 *	@version	1.0.1.1
 *	@author		Nick Shallery	(nicknide@gmail.com)
 *	@copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/


#if			!defined(__LOLIX__SOLA__LINE_S__K_IN_G__)
#define		__LOLIX__SOLA__LINE_S__K_IN_G__


#if			!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)
	#include	"../lolix_cfg.h"
#endif	//	!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)

#if			!defined(__LOLIX__SOLA__VEC__NICK__K_IN_G__)
	#include	"./vec.hpp"
#endif		//	!defined(__LOLIX__SOLA__VEC__NICK__K_IN_G__)


namespace lolix{namespace sola{
	template<typename _Ty>
	class	line_s	//	line_segment
	{
		typedef	line_s<_Ty>	this_type;
	public:
		typedef	vec<3, _Ty>	value_type;
		typedef	_Ty				element_type;

		line_s<_Ty>(void){}
		template<typename _T0, typename _T1>
		LOLIX_INLINE_CALL	line_s<_Ty>(const _T0& t0, const _T1& t1){v[0] = t0; v[1] = t1;}
		template<typename _To>
		LOLIX_INLINE_CALL	line_s<_Ty>(const line_s<_To>& o){ v[0] = o.v[0], v[1] = o.v[1]; }
		template<typename _T0, typename _T1>
		LOLIX_INLINE_CALL	this_type&	operator()(const _T0& t0, const _T1& t1){v[0] = t0; v[1] = t1;}
		template<typename _To>
		LOLIX_INLINE_CALL	this_type&	operator()(const line_s<_To>& o){ v[0] = o.v[0], v[1] = o.v[1];}

		LOLIX_INLINE_CALL	size_type	size(void)const		{ return (v[1] - v[0]).size(); }
		LOLIX_INLINE_CALL	size_type	size_p2(void)const	{ return (v[1] - v[0]).size_pow_2(); }

		LOLIX_INLINE_CALL	size_type	length(void)const	{ return size(); }
		LOLIX_INLINE_CALL	size_type	length_p2(void)const{ return size_p2(); }

		value_type	v[2];

	};


	//	V*t + D = L(t)
	template<typename _Ty>
	class line
	{
		typedef	line<_Ty>	this_type;
	public:
		typedef	vec<3, _Ty>	value_type;
		typedef	_Ty				element_type;
		line<_Ty>(void){}
		template<typename _Tv, typename _Td>
		LOLIX_INLINE_CALL	line<_Ty>(const _Tv& tv, const _Td& td): v(tv), d(td){}
		template<typename _To>
		LOLIX_INLINE_CALL	line<_Ty>(const line_s<_To>& o):v(o.v), d(o.v[1]-o.v[0]){}
		template<typename _To>
		LOLIX_INLINE_CALL	line<_Ty>(const line<_To>& o): v(o.v), d(o.d){}
		template<typename _Tv, typename _Td>
		LOLIX_INLINE_CALL	this_type&	operator()(const _Tv& tv, const _Td& td){v = tv; d = td;}
		template<typename _To>
		LOLIX_INLINE_CALL	this_type&	operator()(const line_s<_To>& o){ v = o.v[0], d = o.v[1]-o.v[0];}
		template<typename _To>
		LOLIX_INLINE_CALL	this_type&	operator()(const line<_To>& o){v = o.v; d = o.d;}

		LOLIX_INLINE_CALL	this_type&	normalize(void){v.normalize_self();return *this;}

		template<typename _Tt, size_type _Dim>
		LOLIX_INLINE_CALL	vec<_Dim, _Tt> shadow(vec<_Dim, _Tt> const& p)
		{
			vec<3, _Tt> dp = p - d;
			vec<_Dim, _Tt> n = v.dot(dp.normalize()).dot(v);
			return p + dp * n;
		}

		value_type	v, d;	//	vector(normalized), direction
	};
}}

#endif	//	!defined(__LOLIX__SOLA__LINE_S__K_IN_G__)
